package com.moyun.controller.common;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.moyun.common.annotation.OperLog;
import com.moyun.common.aspect.BusinessType;
import com.moyun.model.common.PageDTO;
import com.moyun.model.common.PageParam;
import com.moyun.model.common.PageResult;
import com.moyun.model.common.R;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <h3>moyun-base</h3>
 * <p>通用Controller</p>
 *
 * @param <V> 实体类VO
 * @param <E> 实体类
 * @param <P> 带其他参数的实体类
 * @param <T> id主键类型
 * @author : ybx
 * @date : 2021-10-12 18:37:48
 **/

public class CommonController<V, E, P, T> {

    // 实际上注入的是 EServiceImpl 实现类对象
    @Autowired
    private IService<E> commonService;

    @ApiOperation("分页查询(查)")
    @ApiOperationSupport(order = 4)
    @PostMapping("page")
    @OperLog(operModul = "", operType = BusinessType.QUERY, operDesc = "")
    public R<PageResult<E>> page(@RequestBody @Validated PageParam<E> params) {
        PageDTO pageParams = params.getPageParams();
        if (pageParams == null) {
            params.setPageParams(new PageDTO());
        }

        // 1.构建临时分页对象
        Page<E> pageTemp = new Page<>(pageParams.getCurrent(), pageParams.getSize());
        // 2.构建查询条件
        QueryWrapper<E> queryWrapper = new QueryWrapper<>();
        Page<E> page;
        // 3.判断是否有排序需求,并完善最终的分页对象
        String sortField = pageParams.getSortField();
        if (StringUtils.isEmpty(sortField)) {
            page = this.commonService.page(pageTemp, queryWrapper);
        } else {
            // 将前端传递的排序字段(驼峰)转换为db字段(下划线)
            String[] sortFields = sortField.split(",");
            List<String> sortColumns = Arrays.stream(sortFields).map(StrUtil::toUnderlineCase).collect(Collectors.toList());
            if (pageParams.isAsc()) {
                page = this.commonService.page(pageTemp, queryWrapper.orderByAsc(StrUtil.join(",", sortColumns)));
            } else {
                page = this.commonService.page(pageTemp, queryWrapper.orderByDesc(StrUtil.join(",", sortColumns)));
            }
        }
        return R.ok(new PageResult<>(page.getTotal(), page.getRecords()));
    }

    @ApiOperation("列表查询")
    @GetMapping("list")
    @OperLog(operModul = "", operType = BusinessType.QUERY, operDesc = "")
    public R<List<E>> list() {
        QueryWrapper<E> queryWrapper = new QueryWrapper<>();
        List<E> list = this.commonService.list(queryWrapper);
        return R.ok(list);
    }

    @ApiOperation("主键id查询")
    @GetMapping("get/{id}")
    @OperLog(operModul = "", operType = BusinessType.QUERY, operDesc = "")
    public R<E> get(@PathVariable("id") T id) {
        E entity = commonService.getById((Serializable) id);
        return R.ok(entity);
    }

    @ApiOperation("添加数据(增)")
    @ApiOperationSupport(order = 1)
    @OperLog(operModul = "", operType = BusinessType.INSERT, operDesc = "")
    @PostMapping("save")
    public R save(@RequestBody E entity) {
        boolean isSave = this.commonService.save(entity);
        return isSave ? R.ok(0, "操作成功") : R.error(1, "操作失败");
    }

    @ApiOperation("软删除(删)")
    @ApiOperationSupport(order = 2)
    @OperLog(operModul = "", operType = BusinessType.DELETE, operDesc = "")
    @DeleteMapping("del-soft/{id}")
    public R delSoft(@PathVariable("id") T id) {
        boolean isDelete = this.commonService.removeById((Serializable) id);
        return isDelete ? R.ok(0, "操作成功") : R.error(1, "操作失败");
    }

    @ApiOperation("硬删除")
    @OperLog(operModul = "", operType = BusinessType.DELETE, operDesc = "")
    @DeleteMapping("del-phy/{id}")
    public R delPhy(@PathVariable("id") T id) {
        // 物理删除暂未实现
        boolean isDelete = false;
        return isDelete ? R.ok(0, "操作成功") : R.error(1, "操作失败");
    }

    @ApiOperation("更新数据(改)")
    @ApiOperationSupport(order = 3)
    @OperLog(operModul = "", operType = BusinessType.UPDATE, operDesc = "")
    @PutMapping("/update")
    public R update(@RequestBody() E entity) {
        boolean isUpdate = this.commonService.updateById(entity);
        return isUpdate ? R.ok(0, "操作成功") : R.error(1, "操作失败");
    }
}